package com.competitions.videoedithelper.utils;

import com.competitions.videoedithelper.entity.VideoInfo;
import org.jaudiotagger.audio.AudioFileIO;
import org.jaudiotagger.audio.mp3.MP3AudioHeader;
import org.jaudiotagger.audio.mp3.MP3File;
import org.springframework.web.multipart.MultipartFile;
import ws.schild.jave.MultimediaInfo;
import ws.schild.jave.MultimediaObject;

import java.io.*;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author 盛旭雯
 */
public class UploadFileUtil {

    //private static final String FFMPEG_PATH="C:\\video_edit_helper\\lib\\ffmpeg\\bin\\ffmpeg.exe";
    private static final String FFMPEG_PATH="/usr/bin/ffmpeg";

    /**
     * 文件允许格式
     */
    private static String[] allowFiles = { ".mp4", ".ogg", ".webm", ".mov", ".avi", ".mkv", ".m4v", ".wmv",
            ".asf", ".asx", ".rm", ".rmvb", ".3gp", ".dat", ".flv", ".vob" };

    public VideoInfo createFile(MultipartFile multipartFile,int uploadUserId) {

        VideoInfo videoInfo=new VideoInfo();
        boolean flag = false;
        int fileType=0;
        String fileName = multipartFile.getOriginalFilename();
        long fileSize=multipartFile.getSize();

        // 判断文件不为空
        if (fileSize != 0 && !multipartFile.isEmpty()) {
            // 判断文件大小
            // 文件最大500M
            long uploadMaxsize = 500 * 1024 * 1024;
            if (fileSize <= uploadMaxsize) {
                // 文件类型判断
                if (this.checkFileType(fileName)) {
                    flag = true;
                    fileType=1;
                } else {
                    System.out.println("文件类型不允许");
                }
            } else {
                System.out.println("文件大小超范围");
            }
        } else {
            System.out.println("文件为空");
        }

        if (flag) {
            String remotePath="http://121.43.142.18:8066/userfiles/videos/initVideos/"+uploadUserId+"/";
            //String filePathDir ="C:/uploadTest/";
            String filePathDir = "/root/home/userfiles/videos/initVideos/"+uploadUserId+"/";
            File saveFileDir = new File(filePathDir);
            System.out.println("上传文件的地址："+filePathDir);
            boolean isCreateSuccess = true;
            if (!saveFileDir.exists()) {
                isCreateSuccess=saveFileDir.mkdirs();
            }
            if(!isCreateSuccess){
                System.out.println("创建文件夹失败");
                return null;
            }
            assert fileName != null;
            String newFileName= UUID.randomUUID()+fileName.substring(fileName.lastIndexOf("."));
            // 绝对路径
            String absolutePathDir = filePathDir+newFileName;
            System.out.println("保存的绝对路径：" + absolutePathDir);
            File saveFile = new File(absolutePathDir);
            // 转入文件
            try {
                multipartFile.transferTo(saveFile);
            } catch (IllegalStateException | IOException e) {
                e.printStackTrace();
            }
            if(!saveFile.exists()){
                return null;
            }
            Timestamp addTime = new Timestamp(System.currentTimeMillis());
            String status="init";
            String videoLength=null;
            String idVarchar="";
            //String ffmpegPath="C:\\video_edit_helper\\lib\\ffmpeg\\bin\\ffmpeg.exe";
            String ffmpegPath="/usr/bin/ffmpeg";
            String time=null;
            try{
                time=getVideoTime(absolutePathDir);
            }catch (Exception e){
                System.out.println("获取时长失败");
            }
            assert time != null;
            int duration=getTimelen(time);
            int initType=1;
            String videoType=getFileExt(fileName);
            String imageName=newFileName.substring(0,newFileName.lastIndexOf("."))+".jpg";
            //String imagePathDir="C:/uploadTest/images/";
            String imagePathDir="/root/home/userfiles/images/"+uploadUserId+"/";
            File imageSavePath=new File(imagePathDir);
            if (!imageSavePath.exists()) {
                isCreateSuccess=imageSavePath.mkdirs();
            }
            if(!isCreateSuccess){
                System.out.println("创建文件夹失败");
                return null;
            }
            try {
                getImage(ffmpegPath,absolutePathDir,imagePathDir+imageName);
            }catch (Exception e){
                System.out.println("获取封面失败");
            }
            String imageUrl="http://121.43.142.18:8066/userfiles/images/"+uploadUserId+"/"+imageName;
            String name=fileName.substring(0,fileName.lastIndexOf("."));
            videoInfo.setName(name);
            videoInfo.setVideoSize(fileSize+"");
            videoInfo.setAddTime(addTime);
            videoInfo.setStatus(status);
            videoInfo.setVideoLength(videoLength);
            videoInfo.setIdVarchar(idVarchar);
            videoInfo.setVideoTime(time);
            videoInfo.setVideoDuration(duration);
            videoInfo.setImageUrl(imageUrl);
            videoInfo.setFileType(fileType);
            videoInfo.setInitType(initType);
            videoInfo.setUploadUserId(uploadUserId);
            videoInfo.setVideoType(videoType);
            videoInfo.setFilePath(absolutePathDir);
            videoInfo.setRemotePath(remotePath+newFileName);
            return videoInfo;
        } else {
            return null;
        }
    }

    /**
     * 文件类型判断
     * @param fileName 文件名称
     * @return boolean
     */
    private boolean checkFileType(String fileName) {
        for (String ext : allowFiles) {
            if (fileName.toLowerCase().endsWith(ext)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取文件扩展名
     * @param fileName 文件名称
     * @return String
     */
    private String getFileExt(String fileName) {
        return fileName.substring(fileName.lastIndexOf("."));
    }

    /**
     * 获取视频总时间
     * @param videoPath  视频路径
     * @return int
     */
    public static String getVideoTime(String videoPath) throws IOException {
        List<String> commands = new ArrayList<>();
        commands.add(FFMPEG_PATH);
        commands.add("-i");
        commands.add(videoPath);
        //模拟cmd指令发送
        ProcessBuilder builder = new ProcessBuilder();
        builder.command(commands);
        final Process p = builder.start();

        //从输入流中读取视频信息
        BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        br.close();

        //从视频信息中解析时长
        String regexDuration = "Duration: (.*?), start: (.*?), bitrate: (\\d*) kb/s";
        Pattern pattern = Pattern.compile(regexDuration);
        Matcher m = pattern.matcher(sb.toString());
        if (m.find()) {
            return m.group(1);
        }
        return null;
    }

    /**
     * 秒数转化为格式:"00:00:10"
     */
    public static String getTime(int duration) {
        String time;
        if (duration<60) {
            if(duration<10){
                time="00:00:0"+duration;
            }else {
                time="00:00:"+duration;
            }
        }else if(duration/60<60){
            if(duration/60<10){
                time="00:0"+duration/60;
            }else {
                time="00:"+duration/60;
            }
            if(duration%60<10){
                time+=":0"+duration%60;
            }else {
                time+=":"+duration%60;
            }
        }else {
            if(duration/3600<10){
                time="0"+duration/3600;
            }else {
                time=""+duration/3600;
            }
            if ((duration%3600)/60<10){
                time+=":0"+(duration%3600)/60;
            }else {
                time+=":"+(duration%3600)/60;
            }
            if ((duration%3600)%60<10){
                time+=":0"+(duration%3600)%60;
            }else {
                time+=":"+(duration%3600)%60;
            }
        }
        System.out.println(time);
        return time;
    }

    /**
     * 格式:"00:00:10.68" 转化为秒数
     */
    public static int getTimelen(String timelen) {
        int min = 0;
        String[] strs = timelen.split(":");
        if (strs[0].compareTo("0") > 0) {
            min += Integer.parseInt(strs[0]) * 60 * 60;
        }
        if (strs[1].compareTo("0") > 0) {
            min += Integer.parseInt(strs[1]) * 60;
        }
        if (strs[2].compareTo("0") > 0) {
            if(strs[2].contains(".")){
                min += Math.round(Float.parseFloat(strs[2]));
            }else {
                min += Integer.parseInt(strs[2]);
            }
        }
        return min;
    }

    private void getImage(String ffmpegPath, String videoPath, String imageUrl) throws IOException, InterruptedException {
        ProcessBuilder processBuilder = new ProcessBuilder(ffmpegPath, "-i", videoPath, "-ss", "1", "-frames:v", "1", imageUrl);
        Process process = processBuilder.start();

        InputStream stderr = process.getErrorStream();
        InputStreamReader isr = new InputStreamReader(stderr);
        BufferedReader br = new BufferedReader(isr);
        String line;
        while ((line = br.readLine()) != null) {
        }
        process.waitFor();
        br.close();
        isr.close();
        stderr.close();
    }
}
